package org.mat.copybook;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import org.mat.copybook.constant.CopybookStyle;
import org.mat.copybook.constant.LayoutConstants;
import org.mat.copybook.constant.SizeEnum;
import org.mat.copybook.data.Copybook;
import org.mat.copybook.data.LayoutConfig;
import org.mat.copybook.data.Page;
import org.mat.copybook.layout.DefaultLayouter;


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName: CopybookRenderer
 * @Date: 2022/9/18
 * @author: xinhe65045
 * @Version: 1.0
 * @Description: 字帖绘制器
 * <p>
 * TODO 提供字帖生成入口-默认版本，保存图片到本地，并返回路径
 * TODO 提供字帖生成入口-支持可选参数
 */
public class CopybookRenderer {
    // TODO 这两个写死的变量，需要后期替换掉
    private static final String outputPath = "D:\\workspace\\mat-cloud\\mat-utils-copybook\\target\\output\\";
    private static final String fontPath = "D:\\workspace\\mat-cloud\\mat-utils-copybook\\src\\main\\resources\\fonts\\";

    /**
     * 绘制默认的字帖图片
     *
     * @param text 待生成字帖的文本
     * @return 图片路径
     */
    public static String drawDefaultCopybookImage(String text) throws Exception {
        // 定义生成的字帖图片路径
        //TODO 初始化默认字帖图片路径，考虑使用系统默认临时文件目录或进程所在目录，后续支持可配置
        //TODO 初始化默认字体目录，考虑使用进程所在目录，后续支持可配置
        //TODO 支持根据Copybook信息动态生成文件名
        String copybookImagePath = outputPath + "foo.png";

        //TODO 暂时写死，后续根据入参封装布局配置对象
        LayoutConfig layoutConfig = new LayoutConfig();

        //TODO 创建Copybook对象，传入初始化参数
        Copybook copybook = new Copybook();
        copybook.setContent(text);
        copybook.setLayoutConfig(layoutConfig);
        //TODO 初始化字帖格式配置，具体配置项待列举，当前方法取默认配置
        // - 字体
        // - 颜色
        // - 拼音
        // - 边框颜色
        // - 单元格大小
        // - 行距
        // - ......
        // - 图片路径
        // - 字体路径

        //TODO 计算布局信息
        DefaultLayouter.calculationLayout(copybook);

        //TODO 根据Copybook对象信息，绘制图片
        List<BufferedImage> bufferedImageList = drawCopybookImage(copybook);

        // 输出图片文件
        writeImageFile(copybookImagePath, bufferedImageList);

        // 返回图片路径
        return copybookImagePath;
    }

    /**
     * 输出图片文件
     * TODO 支持自定义文件格式
     *
     * @param copybookImagePath 字帖图片路径
     * @param bufferedImageList 图片内容
     * @throws IOException
     */
    public static void writeImageFile(String copybookImagePath, List<BufferedImage> bufferedImageList) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        ImageIO.write(bufferedImageList.get(0), "png", output);
        FileUtil.writeBytes(output.toByteArray(), new File(copybookImagePath));
    }

    /**
     * 输出图片文件
     * TODO 支持自定义文件格式
     *
     * @param copybookImagePath 字帖图片路径
     * @param bufferedImage     图片内容
     * @throws IOException
     */
    public static void writeImageFile(String copybookImagePath, BufferedImage bufferedImage) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "png", output);
        FileUtil.writeBytes(output.toByteArray(), new File(copybookImagePath));
    }


    /**
     * 绘制字帖图像并返回
     * <p>
     * TODO 拆分方法，按背景、页眉、主内容、页脚依次生成
     *
     * @param copybook 字帖数据
     * @return 图像内容
     * @throws Exception
     */
    public static List<BufferedImage> drawCopybookImage(Copybook copybook) throws Exception {
        List<BufferedImage> bufferedImageList = new ArrayList<>();
        List<Page> pageList = copybook.getPageList();
        LayoutConfig layoutConfig = copybook.getLayoutConfig();

        for (Page page : pageList) {
            // 绘制BufferedImage
            BufferedImage bufferedImage = new BufferedImage(SizeEnum.A4_WIDTH.getValue(), SizeEnum.A4_HEIGHT.getValue(), BufferedImage.TYPE_INT_BGR);
            Graphics2D graphics2D = bufferedImage.createGraphics();
            // 白色的背景
            graphics2D.setBackground(Color.WHITE);
            // 通过使用当前绘图表面的背景色进行填充来清除指定的矩形。
            graphics2D.clearRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());

            //region 页眉
            //TODO 支持传入字帖页眉内容和字体
            Font font = new Font(CopybookStyle.font.getName(), Font.BOLD, 50);
            graphics2D.setFont(font);
            graphics2D.setColor(Color.BLACK);
            graphics2D.drawString("测试页眉", 100, 100);
            //endregion

            //TODO 先画个空白页，铺满单元格
            Integer currentPageHeightPosition = 100 + 200;
            Integer areaHeight = layoutConfig.getAreaHeight();
            Integer cellWidth = LayoutConstants.CellSize.CELL_WIDTH;
            List<String> pageContent = page.getPageContent();
            for (String s : pageContent) {
                Integer columnsPerRow = layoutConfig.getColumnsPerRow();
                Integer rowMarginLeft = 100;

                //TODO 拼音
                Integer heightPinyin = 80;

                int x1Pinyin = rowMarginLeft;
                int x2Pinyin = rowMarginLeft + cellWidth * columnsPerRow + cellWidth; // 当前单元格x轴最大值
                int y1Pinyin = currentPageHeightPosition;
                int y2Pinyin = currentPageHeightPosition + heightPinyin;

                graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                graphics2D.drawImage(drawPinyin(),
                        x1Pinyin,
                        y1Pinyin, null);

                // 设置画笔
                BasicStroke line = new BasicStroke(1,
                        BasicStroke.CAP_BUTT,
                        BasicStroke.JOIN_MITER
                );
                graphics2D.setStroke(line);
                graphics2D.setColor(Color.GREEN);
                Font fontCellPinyin = new Font(CopybookStyle.font.getName(), Font.BOLD, 60);
                graphics2D.setFont(fontCellPinyin);
                graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                // 横线
                graphics2D.drawLine(x1Pinyin, y1Pinyin, x2Pinyin, y1Pinyin);
                // 竖线
                graphics2D.drawLine(x1Pinyin, y1Pinyin, x1Pinyin, y2Pinyin);
                graphics2D.drawLine(x2Pinyin, y1Pinyin, x2Pinyin, y2Pinyin);

                graphics2D.setFont(fontCellPinyin);
                graphics2D.setColor(Color.BLACK);
                graphics2D.drawString("pinyin", x1Pinyin + 30, y2Pinyin - 20);

                currentPageHeightPosition = currentPageHeightPosition + heightPinyin;

                //TODO 田字格
                Integer heightTian = 180;
                for (int i = 0; i <= columnsPerRow; i++) {


                    // 定义基准点
                    int x1Tian = rowMarginLeft + cellWidth * i; // 当前单元格x轴最小值
                    int x2Tian = rowMarginLeft + cellWidth * i + cellWidth; // 当前单元格x轴最大值
                    int y1Tian = currentPageHeightPosition; // 当前单元格y轴最小值
                    int y2Tian = currentPageHeightPosition + heightTian; // 当前单元格y轴最大值

                    graphics2D.setStroke(line);
                    graphics2D.setColor(Color.GREEN);
                    graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                    graphics2D.drawImage(drawTian(),
                            x1Tian,
                            y1Tian, null);

                    // 两条横线
                    graphics2D.drawLine(x1Tian, y1Tian, x2Tian, y1Tian);
                    graphics2D.drawLine(x1Tian, y2Tian, x2Tian, y2Tian);

                    // 两条竖线
                    graphics2D.drawLine(x1Tian, y1Tian, x1Tian, y2Tian);
                    graphics2D.drawLine(x2Tian, y1Tian, x2Tian, y2Tian);

                    // 中间十字
                    BasicStroke dottedLine = new BasicStroke(1,
                            BasicStroke.CAP_BUTT,
                            BasicStroke.JOIN_MITER,
                            5f,
                            new float[]{5, 2},
                            0);
                    graphics2D.setStroke(dottedLine);

                    graphics2D.drawLine(x1Tian, (y1Tian + y2Tian) / 2, x2Tian, (y1Tian + y2Tian) / 2);
                    graphics2D.drawLine((x1Tian + x2Tian) / 2, y1Tian, (x1Tian + x2Tian) / 2, y2Tian);


                    Font fontCell = new Font(CopybookStyle.font.getName(), Font.BOLD, 100);
                    graphics2D.setFont(fontCell);
                    graphics2D.setColor(Color.LIGHT_GRAY);
                    if (i == 0) {
                        graphics2D.setColor(Color.BLACK);
                    }
                    graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    graphics2D.drawString(s, x1Tian + 30, y2Tian - 50);
                }
                currentPageHeightPosition = currentPageHeightPosition + heightTian;
                currentPageHeightPosition = currentPageHeightPosition + 20;

            }


            //endregion

            graphics2D.dispose();

            bufferedImageList.add(bufferedImage);

        }


        return bufferedImageList;


        //TODO 绘制基础布局

        //TODO 绘制页眉

        //TODO 绘制主内容

        //TODO 绘制页脚

    }


    /**
     * 绘制字帖图像并返回
     * <p>
     * TODO 拆分方法，按背景、页眉、主内容、页脚依次生成
     *
     * @return 图像内容
     * @throws Exception
     */
    public static BufferedImage drawCopybookImage() throws Exception {

        // 绘制BufferedImage
        BufferedImage bufferedImage = new BufferedImage(SizeEnum.A4_WIDTH.getValue(), SizeEnum.A4_HEIGHT.getValue(), BufferedImage.TYPE_INT_BGR);
        Graphics2D graphics2D = bufferedImage.createGraphics();
        // 白色的背景
        graphics2D.setBackground(Color.WHITE);
        // 通过使用当前绘图表面的背景色进行填充来清除指定的矩形。
        graphics2D.clearRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight());

        //region 页眉
        //TODO 支持传入字帖页眉内容和字体
        Font font = new Font(CopybookStyle.font.getName(), Font.BOLD, 50);
        graphics2D.setFont(font);
        graphics2D.setColor(Color.BLACK);
        graphics2D.drawString("测试页眉", 100, 100);
        //endregion

        //TODO 先画个空白页，铺满单元格


        //region 画拼音格子
        // 先画拼音，再画文字
        for (int i = 0; i < 5; i++) {
            graphics2D.drawImage(drawPinyin(),
                    100 + 180 * i,
                    300, null);

            //画笔颜色
            Color color = Color.GREEN;
            graphics2D.setColor(color);

            BasicStroke dottedLine = new BasicStroke(1,
                    BasicStroke.CAP_BUTT,
                    BasicStroke.JOIN_MITER,
                    5f,
                    new float[]{5, 2},
                    0);
            graphics2D.setStroke(dottedLine);

            Integer width = 180;
            Integer height = 80;

            double line1Y = 300 - 50;
            double line2Y = 300;
//            double line2Y = 300 + NumberUtil.div((float) height, 3f) * 2;

            //画两条横线
            graphics2D.drawLine(100 + 180 * i, Convert.toInt(line1Y), 100 + 180 * i + width, Convert.toInt(line1Y));
            graphics2D.drawLine(100 + 180 * i, Convert.toInt(line2Y), 100 + 180 * i + width, Convert.toInt(line2Y));

            Font fontCell = new Font(CopybookStyle.font.getName(), Font.BOLD, 60);
            graphics2D.setFont(fontCell);
            graphics2D.setColor(Color.BLACK);
            graphics2D.drawString("ce", 100 + 180 * i + 50, 300);


        }
        //endregion

        //region 画田字格
        // 先画拼音，再画文字
        for (int i = 0; i < 5; i++) {
            graphics2D.drawImage(drawTian(),
                    100 + 180 * i,
                    500, null);

            //画笔颜色
            Color color = Color.GREEN;
            graphics2D.setColor(color);

            BasicStroke line = new BasicStroke(1,
                    BasicStroke.CAP_BUTT,
                    BasicStroke.JOIN_MITER
            );

            Integer width = 180;
            Integer height = 180;

            double line1Y = 500 - 180;
            double line2Y = 500;
//            double line2Y = 300 + NumberUtil.div((float) height, 3f) * 2;

            //画两条横线
            graphics2D.drawLine(100 + 180 * i, Convert.toInt(line1Y), 100 + 180 * i + width, Convert.toInt(line1Y));
            graphics2D.drawLine(100 + 180 * i, Convert.toInt(line2Y), 100 + 180 * i + width, Convert.toInt(line2Y));


            graphics2D.drawLine(100 + 180 * i, 500 - height, 100 + 180 * i, 500);
            graphics2D.drawLine(100 + 180 * i + width, 500 - height, 100 + 180 * i + width, 500);

            BasicStroke dottedLine = new BasicStroke(1,
                    BasicStroke.CAP_BUTT,
                    BasicStroke.JOIN_MITER,
                    5f,
                    new float[]{5, 2},
                    0);
            graphics2D.setStroke(dottedLine);

            graphics2D.drawLine(100 + 180 * i, 500 - height / 2, 100 + 180 * i + width, 500 - height / 2);
            graphics2D.drawLine(100 + 180 * i + width / 2, 500 - height, 100 + 180 * i + width / 2, 500);


            Font fontCell = new Font(CopybookStyle.font.getName(), Font.BOLD, 100);
            graphics2D.setFont(fontCell);
            graphics2D.setColor(Color.BLACK);
            graphics2D.drawString("测", 100 + 180 * i + 50, 500 - 50);


        }
        //endregion

        graphics2D.dispose();


        return bufferedImage;


        //TODO 绘制基础布局

        //TODO 绘制页眉

        //TODO 绘制主内容

        //TODO 绘制页脚

    }

    public static BufferedImage drawTian() {
        Integer width = 180;
        Integer height = 180;

//        log.debug("ConreteCell，width:{},height:{}",width,height);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        Graphics2D g = image.createGraphics();
        //透明背景
        image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g.dispose();
        return image;
    }

    public static BufferedImage drawPinyin() {
        Integer width = 180;
        Integer height = 80;

//        log.debug("ConreteCell，width:{},height:{}",width,height);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
        Graphics2D g = image.createGraphics();
        //透明背景
        image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g.dispose();
        return image;
    }

    public static void main(String[] args) {

        //需要些的字
        String text = "这是一段测试内容屈渊孟甫韩愈禹锡仲龚";

        String copybookImagePath = null;
        try {
            copybookImagePath = drawDefaultCopybookImage(text);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(copybookImagePath);
    }
}
